package com.eagle.parser;

import com.sun.source.tree.*;
import com.sun.source.util.JavacTask;
import com.sun.source.util.TreeScanner;
import com.sun.tools.javac.api.JavacTool;
import com.sun.tools.javac.file.JavacFileManager;

import com.sun.tools.javac.util.Context;


import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;

import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class JavaParser {
    private static final String path = "d://FpyzdbCshszMicroService.java";

    private JavacFileManager fileManager;
    private JavacTool javacTool;

    private static List<String> importInfos=new ArrayList<String>();

    private static List<MethodInfo> methodInfos=new ArrayList<>();

    public JavaParser() {
        Context context = new Context();
        fileManager = new JavacFileManager(context, true, Charset.defaultCharset());
        javacTool = new JavacTool();
    }

    public void parseJavaFiles() {
        Iterable<? extends JavaFileObject> files = fileManager.getJavaFileObjects(path);
        JavaCompiler.CompilationTask compilationTask = javacTool.getTask(null, fileManager, null, null, null, files);
        JavacTask javacTask = (JavacTask) compilationTask;
        try {
            Iterable<? extends CompilationUnitTree> result = javacTask.parse();
            for (CompilationUnitTree tree : result) {
                tree.accept(new SourceVisitor(), null);
                System.out.println("看这里-----------");
                //formatPtrln("tree: %s",tree);
//                ClassOrInterfaceDeclaration declaration=tree;
//                Optional<JavadocComment> javadocComment = declaration.getJavadocComment();
//                formatPtrln("tree: %s",tree.g);
                System.out.println("结束了-----------");
            }
            //System.out.println(importInfos);
            //System.out.println(methodInfos);
            for(MethodInfo methodInfo:methodInfos){
                System.out.println(methodInfo.toString());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    static class SourceVisitor extends TreeScanner<Void, Void> {

        private String currentPackageName = null;

        private List<ParameterInfo> params=new ArrayList<>();

        @Override
        public Void visitCompilationUnit(CompilationUnitTree node, Void aVoid) {
            //formatPtrln("package name: %s",node.getPackageName());
            currentPackageName=node.getPackageName().toString();
            return super.visitCompilationUnit(node, aVoid);
        }

        public Void visitImport(ImportTree node, Void var2) {
//            formatPtrln("import tree: %s",
//                    node.getQualifiedIdentifier());
            String imports=node.getQualifiedIdentifier().toString();

            System.out.println(imports);

            importInfos.add(imports);
            return null;
        }


        public Void visitLabeledStatement(LabeledStatementTree node, Void avoid) {
            System.out.println("测试----------------------------------------------");
            formatPtrln(node.getLabel().toString());
            return null;
        }



        @Override
        public Void visitVariable(VariableTree node, Void aVoid) {
//            formatPtrln("variable name: %s, type: %s, kind: %s, package: %s",
//                    node.getName(), node.getType(), node.getKind(), currentPackageName);

            formatPtrln(node.toString());

            return null;
        }

        public Void visitMethod(MethodTree node, Void mVoid) {
//            formatPtrln("method name: %s, parameter: %s, kind: %s, ReceiverParameter: %s , ReturnType： %s , TypeParameters: %s",
//                    node.getName(), node.getParameters(), node.getKind(), node.getReceiverParameter(),node.getReturnType(),node.getTypeParameters());
//            formatPtrln("method plus: %s,body: %s",node.getModifiers(),node.getBody());
            //formatPtrln("method anno: %s,flags :%s",node.getModifiers().getAnnotations(),node.getModifiers().getFlags());


            Iterator it=node.getModifiers().getAnnotations().iterator();
            while (it.hasNext()){
                String anno=it.next().toString();
                if(anno.startsWith("@Service")){
                    MethodInfo methodInfo=new MethodInfo();
                    methodInfo.setMethodName(node.getName().toString());
                    //formatPtrln("params %s",node.getParameters());
                    Iterator its=node.getParameters().iterator();
                    while (its.hasNext()){
                        String parameter=its.next().toString();
                        ParameterInfo parameterInfo=new ParameterInfo();
                        parameterInfo.setName(parameter.split(" ")[1]);
                        parameterInfo.setType(parameter.split(" ")[0]);
                        params.add(parameterInfo);
                    }
                    methodInfo.setParameter(params);
                    methodInfo.setReturnType(node.getReturnType().toString());

                    anno=anno.substring(anno.indexOf("(")+1,anno.lastIndexOf(")"));
                    //System.out.println(anno);
                    String[] strs=anno.split(",");
                    for(String param:strs){
                        String[] keyValue=param.split("=");
                        String key=keyValue[0];
                        String value=keyValue[1];
                        if(key.trim().equals("serviceName")){
                            value=value.trim().replaceAll("\"","");
                            //formatPtrln("serviceName: %s",value.trim().replaceAll("\"",""));
                            methodInfo.setServiceName(value);
                        }
                        if(key.trim().equals("memo")){
                            value = value.trim().replaceAll("\"","");
                            //formatPtrln("memo: %s",value);
                            methodInfo.setMemo(value);
                        }
                    }
                    methodInfos.add(methodInfo);
                }

            }
            //formatPtrln("method body: %s",node.getBody());

            return null;
        }

        public Void visitAnnotation(AnnotationTree node, Void var2) {
            //formatPtrln("annot type: %s , annot args:%s",node.getAnnotationType(),node.getArguments());
            return null;
        }

        public Void visitAnnotatedType(AnnotatedTypeTree node, Void var2) {
            //formatPtrln(" AnnotatedType: %s , UnderlyingType: %s",node.getAnnotations(),node.getUnderlyingType());
            return null;
        }




    }

    public static void formatPtrln(String format, Object... args) {
        System.out.println(String.format(format, args));
    }

    public static void main(String[] args) {

        new JavaParser().parseJavaFiles();
    }
}
